package com.ywu.application.standard.verify.service;

import com.ywu.boot.utils.RedisUtils;
import com.ywu.common.constant.CommonConstant;
import com.ywu.common.result.CommonResult;
import com.ywu.application.standard.verify.common.VerifyConstant;
import com.ywu.application.standard.verify.config.VerifyConfig;
import com.ywu.application.standard.verify.dto.VerifyDto;
import com.ywu.application.standard.verify.dto.VerifyParamDto;
import com.ywu.application.standard.verify.utils.CacheNameUtils;
import com.ywu.application.standard.verify.utils.VerifyUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Base64;
import java.util.Map;
import java.util.Objects;

/**
 * @ClassName VerifyService
 * @Description 验证码生成 service
 * @Author GroundDemo
 * @Date 2023/11/11 20:04
 * @Version 1.0
 **/
@Service
public class VerifyService {

    private static Logger LOG = LoggerFactory.getLogger(VerifyService.class);

    @Autowired
    private VerifyConfig config;

    /**
     * @Author GroundDemo
     * @Description 生成验证码图片
     * @Date 20:07 2023/11/11
     * @Param [response]
     * @return Map
     **/
    public CommonResult<Object> generateVerifyCodeImage(VerifyParamDto dto) {
        // 构建dto，参数为空填充默认值
        if (Objects.isNull(dto)) {
            dto = new VerifyParamDto();
        }
        buildVerifyParamDto(dto);
        LOG.debug("generateVerifyCodeImage VerifyParamDto is {}", dto);
        Map<String, Object> paramMap = VerifyUtils.generateVerifyImage(dto);
        // ImageIO生成图片
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        try {
            ImageIO.write((BufferedImage) paramMap.get(VerifyConstant.VERIFY_CODE_PIC_KEY), "jpg", baos);
            byte[] bytes = baos.toByteArray();
            // 转换二进制文件为base64格式
            String base64Image = Base64.getEncoder().encodeToString(bytes);
            String imageSrc = "data:image/jpeg;base64," + base64Image;
            VerifyDto verifyDto = new VerifyDto().setVerifyImageStr(imageSrc)
                    .setVerifyKey((String) paramMap.get(VerifyConstant.VERIFY_CODE_REDIS_KEY));
            return CommonResult.success(verifyDto);
        } catch (IOException e) {
            LOG.error("generateVerifyCodeImage image write error {}", e.getMessage());
            return CommonResult.error().setErrorCode(CommonConstant.SERVICE_ERROR_CODE)
                    .setMessage(CommonConstant.SERVICE_ERROR_MESSAGE);
        }
    }

    /**
     * @Author GroundDemo
     * @Description 构建dto，参数为空填充默认值
     * @Date 21:23 2023/11/11
     * @Param [dto]
     * @return void
     **/
    private void buildVerifyParamDto(VerifyParamDto dto) {
        dto.setFontName(StringUtils.isBlank(dto.getFontName()) ? config.getFontName() : dto.getFontName())
                .setHeight(Objects.isNull(dto.getHeight()) ? config.getHeight() : dto.getHeight())
                        .setLen(Objects.isNull(dto.getLen()) ? config.getLen() : dto.getLen())
                        .setWidth(Objects.isNull(dto.getWidth()) ? config.getWidth() : dto.getWidth())
                        .setFontSize(Objects.isNull(dto.getFontSize()) ? config.getFontSize() : dto.getFontSize())
                        .setTypes(CollectionUtils.isEmpty(dto.getTypes()) ? config.getType() : dto.getTypes())
                        .setInterfereSize(Objects.isNull(dto.getInterfereSize()) ? config.getInterfereSize() : dto.getInterfereSize());
    }

    /**
    * @Author GroundDemo
    * @Description 校验验证码
    * @Date 17:05 2024/3/16
    * @Param [dto]
    * @return com.ywu.common.result.CommonResult<java.lang.Object>
    **/
    public CommonResult<Object> verifyLoginCode(VerifyDto dto) {
        String redisKey = CacheNameUtils.getVerifyRedisCacheKey() + ":" + dto.getVerifyKey();
        String verifyCode = RedisUtils.getByKey(redisKey);
        // 判断是否为空
        if (StringUtils.isEmpty(verifyCode)) {
            return CommonResult.error().setErrorCode("verify code is overdue")
                    .setMessage("验证码已过期");
        }
        // 判断code是否相同
        if (!StringUtils.equals(dto.getVerifyCode(), verifyCode)) {
            return CommonResult.error().setErrorCode("verify code check failed")
                    .setMessage("验证码校验失败");
        }
        return CommonResult.success(null);
    }
}
